package c2.group.business.tb;

import c2.advanced.business.base.KvData;
import c2.group.business.GroupBody;
import c2.group.business.base.GroupModule;
import c2.group.business.base.GroupSubModule;
import c2.group.business.tb.base.TBStatus;
import c2.group.business.tb.boss.TBBossModule;
import c2.group.business.tb.ko.TBKoModule;
import c2.group.business.tb.ps.TBPlaySideModule;
import c2.group.business.tb.rival.TBRivalModule;
import c2.group.business.tb.trial.TBTrialModule;
import cate.common.table.d.GDThrone;
import cate.game.pvp.throne.data.TBSeason;
import cate.game.pvp.throne.dto.TBBaseDTO;
import cate.game.pvp.throne.dto.TBGroupDataDTO;
import cate.game.pvp.throne.msg.TBAllDataNotice;
import cate.game.util.IntervalCounter;
import easy.java.dev.note.NoteClass;
import easy.java.dev.note.NoteField;
import lombok.extern.slf4j.Slf4j;

@NoteClass("王座争霸模块")
@Slf4j
public class TBModule extends GroupModule<TBStatus> {

	@NoteField("消息发送")
	public TBGroupMessageModule message = new TBGroupMessageModule();
	@NoteField("消息接收")
	public TBGroupReceiveModule receive = new TBGroupReceiveModule();
	@NoteField("对手库模块")
	public TBRivalModule rival = new TBRivalModule();
	@NoteField("选拔赛模块")
	public TBTrialModule trial = new TBTrialModule();
	@NoteField("淘汰赛模块")
	public TBKoModule ko = new TBKoModule();
	@NoteField("冠军boss模块")
	public TBBossModule boss = new TBBossModule();
	@NoteField("阵容库模块")
	public TBPlaySideModule ps = new TBPlaySideModule();


	private boolean dataReady;

	private IntervalCounter saveTrigger = new IntervalCounter(3600);
	private IntervalCounter noticeTrigger = new IntervalCounter(60);


	public TBModule(GroupBody context) {
		super(context);
	}

	@Override
	protected GroupSubModule[] getSubModules() {
		return new GroupSubModule[]{message,receive,rival,trial,ko,boss,ps};
	}

	@Override
	protected String getStatusKey() {
		return KvData.KEY_THRONE_BATTLE_BASE;
	}

	@Override
	public String getName() {
		return "王座争霸";
	}


	public TBStatus getStatus() {
		return status;
	}

	@Override
	public void initDependent() throws Exception {
		super.initDependent();
		readFromDB();
		checkSeason();
		dataReady = true;
		noticeAll();
	}

	private TBSubModule[] getBusinessModules(){
		return new TBSubModule[]{rival,trial,ko,boss,ps};
	}

	private void readFromDB() {
		for (TBSubModule module : getBusinessModules()) {
			module.readFromBD();
		}
	}

	private void checkSeason() {
		TBSeason curBase = TBSeason.build();
		boolean change = status.season.index != curBase.index;
		if (change) {
			for (TBSubModule module : getBusinessModules()) {
				module.clear();
			}
			status.season.readFrom(curBase);
			status.timeTable.buildTimeTable(table().throne.time, curBase.startTime);
			for (TBSubModule module : getBusinessModules()) {
				module.onEnterNewSeason();
			}
		} else {
			status.season.readFrom(curBase);
		}
	}

	@Override
	protected int getIntervalSeconds() {
		return 1;
	}

	@Override
	protected void onInterval() throws Exception {
		if (!dataReady) {
			return;
		}
		seasonTick();
		periodTick();
		ko.onInterval();
		saveTick();
		noticeTick();
	}


	private void seasonTick() {
		if (status.season.tick()) {
			checkSeason();
			noticeAll();
		}
	}

	private void periodTick() {
		if (status.timeTable.tick()) {
			final byte period = status.timeTable.period;
			for (TBSubModule module : getBusinessModules()) {
				module.onPeriodChange(period);
			}
			noticeAll();
		}
	}

	private void noticeTick(){
		if (needNotice && noticeTrigger.trigger()) {
			needNotice = false;
			noticeAll();
		}
	}

	private void saveTick() {
		if (saveTrigger.trigger()) {
			log.info("[王座争霸]周期性保存begin");
			saveStatus();
			for (TBSubModule module : getBusinessModules()) {
				module.save();
			}
			log.info("[王座争霸]周期性保存begin");
		}
	}


	public void markNeedNotice(){
		needNotice = true;
	}

	private boolean needNotice = false;

	private void noticeAll() {
		needNotice = false;
		TBAllDataNotice notice = new TBAllDataNotice();
		notice.base = new TBBaseDTO(status.season, status.timeTable);
		notice.koBase = ko.getStatus().toDTO();
		notice.boss = boss.getStatus().toDTO();
		for (Integer levelGroup : GDThrone.LevelGroup.ALL) {
			TBGroupDataDTO dataDTO = new TBGroupDataDTO(levelGroup);
			dataDTO.trial = this.trial.getGroup(levelGroup);
			dataDTO.ko = this.ko.getGroup(levelGroup);
			notice.groupMap.put(levelGroup, dataDTO);
		}
		message.noticeAll(notice);
	}
}
